﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace sqlsearcher.Models.Extends
{
    public class MyRichTextBox : RichTextBox
    {
        private const int WM_PAINT = 0x000F;
        private int lockPaint;
        private bool needPaint;
        //private paintHelper pHelp = new paintHelper();

        public void BeginUpdate()
        {
            lockPaint++;
        }

        public void EndUpdate()
        {
            lockPaint--;
            if (lockPaint <= 0)
            {
                lockPaint = 0;
                if (needPaint)
                {
                    this.Refresh();
                    needPaint = false;
                }
            }
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_PAINT:
                    if (lockPaint <= 0)
                    {
                        base.WndProc(ref m);
                    }
                    else
                    {
                        needPaint = true;
                        //pHelp.DefaultWndProc(ref m);
                    }
                    return;
            }

            base.WndProc(ref m);
        }


        Dictionary<string, Color> words = new Dictionary<string, Color>();
        /// <summary>
        /// 设置字符颜色
        /// </summary>
        /// <param name="pWords">关键字</param>
        /// <param name="pColor">所用颜色</param>
        /// <param name="isKeyWord">真时，替换之前设置的颜色。否的话，如果已设置相关关键字，忽略该设置</param>
        public void SetColorWord(IEnumerable<string> pWords, Color pColor, bool isKeyWord)
        {
            foreach (string one in pWords)
            {
                string low = one.ToLower();
                if (words.ContainsKey(low))
                {
                    if (isKeyWord)
                        words[low] = pColor;
                }
                else
                {
                    words.Add(low, pColor);
                }
            }
        }
        /// <summary>
        /// 着色
        /// </summary>
        public void RunColor()
        {
            this.BeginUpdate();//停止绘制
            //文本框改变事件　　　　
            int lastIndex = this.SelectionStart;  //记录修改的位置

            int index = 0;
            int wordStart = -1;//单词的开始位置
            char[] text = this.Text.ToCharArray();//打散每一个字符
            StringBuilder sb = new StringBuilder();
            //尝试取出每一个单词
            while (index < text.Length)
            {
                char chk = text[index];
                if (WhiteSpaceChars.Contains(chk))//是否空白字符
                {
                    if (wordStart >= 0)//空白字符，前面已找到单词的开始位置，这就是单词的结束了
                    {
                        //取出音词
                        string code = sb.ToString();
                        colorWords(code.ToLower(), wordStart);
                        wordStart = -1;
                    }
                    else
                    {
                        //空白字符，未找到词开头，不需作任何处理
                    }
                }
                else
                {
                    //找到非空白字符
                    if (wordStart == -1)//找到词开头了。
                    {
                        sb = new StringBuilder();
                        wordStart = index;
                    }
                    sb.Append(chk);
                }
                index++;//下一字符
            }
            if (sb.Length > 0 && wordStart >= 0)//最后一个词
            {
                string code = sb.ToString();
                colorWords(code.ToLower(), wordStart);
            }
            this.Select(lastIndex, 0);　 //返回修改的位置
            this.SelectionColor = Color.Black;
            this.EndUpdate();//恢复绘制事件            
        }
        /// <summary>
        /// 给单词着色，非关键字改为黑色
        /// </summary>
        /// <param name="pChkWord"></param>
        /// <param name="pStart"></param>
        private void colorWords(string pChkWord, int pStart)
        {
            this.Select(pStart, pChkWord.Length);
            if (words.ContainsKey(pChkWord))
                this.SelectionColor = words[pChkWord];
            else
                this.SelectionColor = Color.Black;
        }
        /// <summary>
        /// 空白字符
        /// </summary>
        public static readonly char[] WhiteSpaceChars = new char[] { (char)0x00, (char)0x01, (char)0x02, (char)0x03, (char)0x04, (char)0x05,
            (char)0x06, (char)0x07, (char)0x08, (char)0x09, (char)0x0a, (char)0x0b, (char)0x0c, (char)0x0d, (char)0x0e, (char)0x0f,
            (char)0x10, (char)0x11, (char)0x12, (char)0x13, (char)0x14, (char)0x15, (char)0x16, (char)0x17, (char)0x18, (char)0x19, (char)0x20,
            (char)0x1a, (char)0x1b, (char)0x1c, (char)0x1d, (char)0x1e, (char)0x1f, (char)0x7f, (char)0x85, (char)0x2028, (char)0x2029 };

    }
}
